﻿using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Singer.Core;
using Singer.Shared;

namespace Singer.Framework.Middlewares;

/// <summary>
/// 全局异常处理中间件
/// </summary>
public class GlobalExceptionHandlerMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<GlobalExceptionHandlerMiddleware> _logger;

    public GlobalExceptionHandlerMiddleware(RequestDelegate next, ILogger<GlobalExceptionHandlerMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (Exception ex)
        {
            string msg = ex.Message;
            IWebHostEnvironment env = context.RequestServices.GetRequiredService<IWebHostEnvironment>();
            if (env.IsDevelopment())
            {
                //如果不是手动抛出的业务异常。认为是系统未处理的异常，在开发环境显示详细堆栈信息，方便找问题。
                if (ex is not CoreException && !string.IsNullOrEmpty(ex.StackTrace))
                    msg += "【异常堆栈】(仅开发环境可见)：" + ex.StackTrace;
                _logger.LogError("【系统异常】：" + msg);
            }
            CoreApiResult result = CoreApiResult.Error(msg);
            if (ex is CoreException exp)
                result.SetErrorCode(exp.Code);
            context.Response.StatusCode = StatusCodes.Status200OK; //http状态码设置为200，表示成功
            context.Response.ContentType = "application/json;charset=utf-8";//设置数据格式
            string jsonResult = JsonUtils.ToJson(result);
            await context.Response.WriteAsync(jsonResult);
        }
    }
}
